using System.Collections.Concurrent;
using Microsoft.Extensions.Caching.Memory;

namespace WeatherSystem.API.Services
{
    /// <summary>
    /// 错误恢复服务实现
    /// </summary>
    public class ErrorRecoveryService : IErrorRecoveryService
    {
        private readonly ILogger<ErrorRecoveryService> _logger;
        private readonly IMemoryCache _cache;
        private readonly ConcurrentDictionary<string, CircuitBreaker> _circuitBreakers;
        private readonly ConcurrentDictionary<string, ComponentHealth> _componentHealths;

        public ErrorRecoveryService(ILogger<ErrorRecoveryService> logger, IMemoryCache cache)
        {
            _logger = logger;
            _cache = cache;
            _circuitBreakers = new ConcurrentDictionary<string, CircuitBreaker>();
            _componentHealths = new ConcurrentDictionary<string, ComponentHealth>();
        }

        public async Task<T> ExecuteWithRetryAsync<T>(
            Func<Task<T>> operation,
            int maxRetries = 3,
            TimeSpan? delay = null,
            Func<Exception, bool>? shouldRetry = null)
        {
            var retryDelay = delay ?? TimeSpan.FromMilliseconds(1000);
            var attempts = 0;
            Exception lastException = null!;

            while (attempts <= maxRetries)
            {
                try
                {
                    var result = await operation();
                    if (attempts > 0)
                    {
                        _logger.LogInformation("操作在第 {Attempt} 次重试后成功", attempts);
                    }
                    return result;
                }
                catch (Exception ex)
                {
                    lastException = ex;
                    attempts++;

                    if (attempts > maxRetries || (shouldRetry != null && !shouldRetry(ex)))
                    {
                        _logger.LogError(ex, "操作在 {MaxRetries} 次重试后仍然失败", maxRetries);
                        throw;
                    }

                    _logger.LogWarning(ex, "操作失败，将在 {Delay}ms 后进行第 {Attempt} 次重试", 
                        retryDelay.TotalMilliseconds, attempts);

                    await Task.Delay(retryDelay);
                    
                    // 指数退避策略
                    retryDelay = TimeSpan.FromMilliseconds(retryDelay.TotalMilliseconds * 1.5);
                }
            }

            throw lastException;
        }

        public async Task ExecuteWithRetryAsync(
            Func<Task> operation,
            int maxRetries = 3,
            TimeSpan? delay = null,
            Func<Exception, bool>? shouldRetry = null)
        {
            await ExecuteWithRetryAsync(async () =>
            {
                await operation();
                return true;
            }, maxRetries, delay, shouldRetry);
        }

        public async Task<T> ExecuteWithFallbackAsync<T>(
            Func<Task<T>> primaryOperation,
            Func<Task<T>> fallbackOperation,
            Func<Exception, bool>? shouldFallback = null)
        {
            try
            {
                return await primaryOperation();
            }
            catch (Exception ex)
            {
                if (shouldFallback == null || shouldFallback(ex))
                {
                    _logger.LogWarning(ex, "主要操作失败，正在执行降级操作");
                    
                    try
                    {
                        var fallbackResult = await fallbackOperation();
                        _logger.LogInformation("降级操作执行成功");
                        return fallbackResult;
                    }
                    catch (Exception fallbackEx)
                    {
                        _logger.LogError(fallbackEx, "降级操作也执行失败");
                        throw new AggregateException("主要操作和降级操作都失败", ex, fallbackEx);
                    }
                }
                else
                {
                    throw;
                }
            }
        }

        public async Task<T> ExecuteWithTimeoutAsync<T>(
            Func<CancellationToken, Task<T>> operation,
            TimeSpan timeout)
        {
            using var cancellationTokenSource = new CancellationTokenSource(timeout);
            
            try
            {
                return await operation(cancellationTokenSource.Token);
            }
            catch (OperationCanceledException) when (cancellationTokenSource.Token.IsCancellationRequested)
            {
                _logger.LogWarning("操作超时，超时时间: {Timeout}ms", timeout.TotalMilliseconds);
                throw new TimeoutException($"操作超时，超时时间: {timeout.TotalMilliseconds}ms");
            }
        }

        public async Task<T> ExecuteWithCircuitBreakerAsync<T>(
            Func<Task<T>> operation,
            string circuitBreakerKey)
        {
            var circuitBreaker = _circuitBreakers.GetOrAdd(circuitBreakerKey, 
                _ => new CircuitBreaker(new CircuitBreakerOptions(), _logger));

            return await circuitBreaker.ExecuteAsync(operation);
        }

        public async Task LogErrorAsync(Exception exception, string context, Dictionary<string, object>? additionalData = null)
        {
            var errorData = new
            {
                Context = context,
                Exception = new
                {
                    Type = exception.GetType().Name,
                    Message = exception.Message,
                    StackTrace = exception.StackTrace
                },
                Timestamp = DateTime.UtcNow,
                AdditionalData = additionalData ?? new Dictionary<string, object>()
            };

            _logger.LogError(exception, "错误记录 - 上下文: {Context}, 数据: {@ErrorData}", context, errorData);

            // 可以在这里添加持久化错误日志的逻辑，如写入数据库或外部日志系统
            await Task.CompletedTask;
        }

        public async Task<SystemHealthStatus> GetSystemHealthAsync()
        {
            var healthStatus = new SystemHealthStatus();
            var issues = new List<string>();

            // 检查数据库连接
            await CheckDatabaseHealthAsync(healthStatus);

            // 检查缓存服务
            CheckCacheHealth(healthStatus);

            // 检查断路器状态
            CheckCircuitBreakerHealth(healthStatus, issues);

            // 检查组件健康状态
            foreach (var component in _componentHealths.Values)
            {
                healthStatus.Components[component.Name] = component;
                
                if (component.Status != "Healthy")
                {
                    issues.Add($"{component.Name}: {component.Description}");
                }
            }

            // 确定整体健康状态
            if (issues.Any())
            {
                healthStatus.Status = issues.Count > healthStatus.Components.Count / 2 ? "Unhealthy" : "Degraded";
                healthStatus.Issues = issues;
            }

            return healthStatus;
        }

        public async Task TriggerRecoveryAsync(string component, Exception exception)
        {
            _logger.LogWarning("触发组件恢复流程: {Component}", component);

            var componentHealth = _componentHealths.GetOrAdd(component, new ComponentHealth
            {
                Name = component,
                Status = "Unhealthy",
                Description = exception.Message,
                LastCheck = DateTime.UtcNow
            });

            componentHealth.Status = "Recovering";
            componentHealth.Description = $"恢复中: {exception.Message}";
            componentHealth.LastCheck = DateTime.UtcNow;

            // 实现特定组件的恢复逻辑
            try
            {
                await ExecuteComponentRecoveryAsync(component, exception);
                
                componentHealth.Status = "Healthy";
                componentHealth.Description = "已恢复";
                _logger.LogInformation("组件 {Component} 恢复成功", component);
            }
            catch (Exception recoveryEx)
            {
                componentHealth.Status = "Failed";
                componentHealth.Description = $"恢复失败: {recoveryEx.Message}";
                _logger.LogError(recoveryEx, "组件 {Component} 恢复失败", component);
                throw;
            }
        }

        private async Task CheckDatabaseHealthAsync(SystemHealthStatus healthStatus)
        {
            var dbHealth = new ComponentHealth
            {
                Name = "Database",
                LastCheck = DateTime.UtcNow
            };

            try
            {
                var startTime = DateTime.UtcNow;
                // 这里可以添加实际的数据库健康检查逻辑
                await Task.Delay(10); // 模拟检查
                dbHealth.ResponseTime = (long)(DateTime.UtcNow - startTime).TotalMilliseconds;
                dbHealth.Status = "Healthy";
                dbHealth.Description = "数据库连接正常";
            }
            catch (Exception ex)
            {
                dbHealth.Status = "Unhealthy";
                dbHealth.Description = ex.Message;
            }

            healthStatus.Components["Database"] = dbHealth;
        }

        private void CheckCacheHealth(SystemHealthStatus healthStatus)
        {
            var cacheHealth = new ComponentHealth
            {
                Name = "Cache",
                LastCheck = DateTime.UtcNow
            };

            try
            {
                var testKey = "health_check_" + Guid.NewGuid();
                var testValue = "test";
                
                _cache.Set(testKey, testValue, TimeSpan.FromMinutes(1));
                var retrievedValue = _cache.Get<string>(testKey);
                
                if (retrievedValue == testValue)
                {
                    cacheHealth.Status = "Healthy";
                    cacheHealth.Description = "缓存服务正常";
                    _cache.Remove(testKey);
                }
                else
                {
                    cacheHealth.Status = "Unhealthy";
                    cacheHealth.Description = "缓存数据不一致";
                }
            }
            catch (Exception ex)
            {
                cacheHealth.Status = "Unhealthy";
                cacheHealth.Description = ex.Message;
            }

            healthStatus.Components["Cache"] = cacheHealth;
        }

        private void CheckCircuitBreakerHealth(SystemHealthStatus healthStatus, List<string> issues)
        {
            var openCircuitBreakers = _circuitBreakers
                .Where(cb => cb.Value.State == CircuitBreakerState.Open)
                .Select(cb => cb.Key)
                .ToList();

            if (openCircuitBreakers.Any())
            {
                issues.Add($"断路器处于打开状态: {string.Join(", ", openCircuitBreakers)}");
            }

            var circuitBreakerHealth = new ComponentHealth
            {
                Name = "CircuitBreakers",
                LastCheck = DateTime.UtcNow,
                Status = openCircuitBreakers.Any() ? "Degraded" : "Healthy",
                Description = openCircuitBreakers.Any() 
                    ? $"{openCircuitBreakers.Count} 个断路器处于打开状态"
                    : "所有断路器正常",
                Metadata = new Dictionary<string, object>
                {
                    ["TotalCircuitBreakers"] = _circuitBreakers.Count,
                    ["OpenCircuitBreakers"] = openCircuitBreakers.Count,
                    ["OpenCircuitBreakerKeys"] = openCircuitBreakers
                }
            };

            healthStatus.Components["CircuitBreakers"] = circuitBreakerHealth;
        }

        private async Task ExecuteComponentRecoveryAsync(string component, Exception exception)
        {
            // 根据组件类型执行不同的恢复策略
            switch (component.ToLower())
            {
                case "database":
                    await RecoverDatabaseConnectionAsync();
                    break;
                case "cache":
                    await RecoverCacheServiceAsync();
                    break;
                case "external_api":
                    await RecoverExternalApiAsync();
                    break;
                default:
                    _logger.LogWarning("未知组件类型，执行通用恢复策略: {Component}", component);
                    await Task.Delay(1000); // 通用延迟
                    break;
            }
        }

        private async Task RecoverDatabaseConnectionAsync()
        {
            _logger.LogInformation("正在恢复数据库连接...");
            await Task.Delay(2000); // 模拟恢复过程
        }

        private async Task RecoverCacheServiceAsync()
        {
            _logger.LogInformation("正在恢复缓存服务...");
            // 清理可能损坏的缓存
            if (_cache is MemoryCache mc)
            {
                mc.Compact(1.0); // 清理所有缓存
            }
            await Task.Delay(1000);
        }

        private async Task RecoverExternalApiAsync()
        {
            _logger.LogInformation("正在恢复外部API连接...");
            await Task.Delay(3000); // 模拟恢复过程
        }
    }

    /// <summary>
    /// 断路器实现
    /// </summary>
    public class CircuitBreaker
    {
        private readonly CircuitBreakerOptions _options;
        private readonly ILogger _logger;
        private volatile CircuitBreakerState _state = CircuitBreakerState.Closed;
        private volatile int _failureCount = 0;
        private DateTime _lastFailureTime = DateTime.MinValue;
        private readonly object _lock = new();

        public CircuitBreakerState State => _state;

        public CircuitBreaker(CircuitBreakerOptions options, ILogger logger)
        {
            _options = options;
            _logger = logger;
        }

        public async Task<T> ExecuteAsync<T>(Func<Task<T>> operation)
        {
            CheckState();

            if (_state == CircuitBreakerState.Open)
            {
                throw new InvalidOperationException("断路器处于打开状态");
            }

            try
            {
                var result = await operation();
                OnSuccess();
                return result;
            }
            catch (Exception ex)
            {
                OnFailure(ex);
                throw;
            }
        }

        private void CheckState()
        {
            if (_state == CircuitBreakerState.Open)
            {
                if (DateTime.UtcNow - _lastFailureTime >= _options.OpenTimeout)
                {
                    lock (_lock)
                    {
                        if (_state == CircuitBreakerState.Open && 
                            DateTime.UtcNow - _lastFailureTime >= _options.OpenTimeout)
                        {
                            _state = CircuitBreakerState.HalfOpen;
                            _logger.LogInformation("断路器从打开状态转为半开状态");
                        }
                    }
                }
            }
        }

        private void OnSuccess()
        {
            if (_state == CircuitBreakerState.HalfOpen)
            {
                lock (_lock)
                {
                    if (_state == CircuitBreakerState.HalfOpen)
                    {
                        _state = CircuitBreakerState.Closed;
                        _failureCount = 0;
                        _logger.LogInformation("断路器从半开状态转为关闭状态");
                    }
                }
            }
            else if (_state == CircuitBreakerState.Closed)
            {
                _failureCount = 0;
            }
        }

        private void OnFailure(Exception exception)
        {
            lock (_lock)
            {
                _failureCount++;
                _lastFailureTime = DateTime.UtcNow;

                if (_state == CircuitBreakerState.HalfOpen || 
                    (_state == CircuitBreakerState.Closed && _failureCount >= _options.FailureThreshold))
                {
                    _state = CircuitBreakerState.Open;
                    _logger.LogWarning("断路器转为打开状态，失败次数: {FailureCount}, 异常: {Exception}", 
                        _failureCount, exception.Message);
                }
            }
        }
    }
}